---
layout: showcase
title: Clustering Map Symbols
---
<!-- commentaire-->
<link rel="stylesheet" type="text/css" href="/css/jquery.qtip.css">
<script type="text/javascript" src="/js/jquery.qtip.min.js"></script>
<script type="text/javascript">


$(function() {

    // initialize tooltips
    $.fn.qtip.defaults.style.classes = 'ui-tooltip-bootstrap';
    $.fn.qtip.defaults.style.def = false;

    $.getJSON('uk-visits.json', function(cities) {

        function map(cont, clustering) {

            var map = $K.map(cont);

            map.loadMap('GBR.svg', function() {
                map.addLayer('context', {
                    styles: {
                        stroke: '#aaa',
                        fill: '#f6f4f2'
                    }
                });
                map.addLayer('regions', {
                    id: 'bg',
                    styles: {
                        stroke: '#d8d6d4',
                        'stroke-width': 10,
                        'stroke-linejoin': 'round'
                    }
                });

                map.addLayer('regions', {
                    title: function(d) { return d.name },
                    styles: {
                        stroke: '#333',
                        fill: '#fff'
                    }
                });

                var scale = $K.scale.sqrt(cities.concat([{ nb_visits: 0 }]), 'nb_visits').range([2, 30]);

                map.addSymbols({
                    type: $K.Bubble,
                    data: cities,
                    clustering: clustering,
                    aggregate: function(cities) {
                        var nc = { nb_visits: 0, city_names: [] };
                        $.each(cities, function(i, c) {
                            nc.nb_visits += c.nb_visits;
                            nc.city_names = nc.city_names.concat(c.city_names ? c.city_names : [c.city_name]);
                        });
                        nc.city_name = nc.city_names[0] + ' and ' + (nc.city_names.length-1) + ' others';
                        return nc;
                    },
                    location: function(city) {
                        return [city.long, city.lat];
                    },
                    radius: function(city) {
                        return scale(city.nb_visits);
                    },
                    tooltip: function(city) {
                        return '<h3>'+city.city_name+'</h3>'+city.nb_visits+' visits';
                    },
                    sortBy: 'radius desc',
                    style: 'fill:#800; stroke: #fff; fill-opacity: 0.5;',
                });
            }, { padding: -75 });

        }

        map('#map0');
        map('#map1', 'k-means');
        map('#map2', 'noverlap');

    });


});



</script>

<p>These maps demonstrate the map symbol clustering features built into Kartograph.js. They all show the same dataset of UK cities sized by the number of people that have visited this website in 2012.</p>

<style type="text/css">
.uk-map {
    width: 31%;
    display: inline-block;
    margin-right: 10px;
    vertical-align: top;
}
.uk-map label {
    text-align: center;
    font-style: italic;
}
.uk-map div {
    height: 400px;
    border: 1px solid #bbb;
    margin-bottom: 1em;
}
</style>

<div class="uk-map">
    <div id="map0"></div>
    <p><b>no clustering</b> — The first map shows the +500 symbols without clustering. London (2k visits) is completely covered by hundreds of cities with only a few visitors. Local maxima such as Leeds and Manchester are hidden, too.</p>
</div>

<div class="uk-map">
    <div id="map1"></div>
    <p><b><em>k</em>-means</b> — Symbols are combined using <a href="http://en.wikipedia.org/wiki/K-means_clustering"><em>k</em>-Means clustering</a>. While the algorithm ensures a fixed number of symbols, it doesn't care about overlappings. Inspired by and uses implementation released along with <a href="http://polymaps.org/ex/cluster.html">this Polymaps example</a>.</p>
</div>
<div class="uk-map">
    <div id="map2"></div>
    <p><b>noverlap</b> — Here symbols are combined only if they overlap, as <a href="http://vis4.net/blog/posts/clean-your-symbol-maps/">described here</a>. This has the advantage of retaining details in regions with less symbols. The name is inspired by a <a href="https://gephi.org/plugins/noverlap/">Gephi plugin</a>.</p>
</div>

<h2>How to do it</h2>

<p>To activate the symbol clustering you need to add two things to the symbol config: the name of clustering technique (either <code>k-means</code> or <code>noverlap</code>) and a function that aggregates data objects of the grouped symbols.</p>

<pre><code>function sumVisits(cities) {
    var total = 0;
    $.each(cities, function(i, city) {
        total += city.visits;
    });
    return { visits: total };
}

map.addSymbols({
    type: Kartograph.Bubble,
    data: cities,
    location: function(city) { return [city.lon, city.lat]; },
    radius: function(d) { return Math.sqrt(city.nb_visits); },
    // name of clustering technique
    clustering: 'noverlap',
    // aggregation function
    aggregate: sumVisits
});</code></pre>

<p>For more details on fine-tuning the symbol clustering, please look up the <a href="/docs/kartograph.js/symbols.html#fine-tuning-k-means">documentation</a>.</p>